import { ActionTree, ActionContext } from "vuex"
import { RouteRecordRaw } from "vue-router";

import { asyncRoutes } from "@/router"
import { RootState } from "@/store"
import type { PermissionState } from "./state"
import { PermissionConstant } from "./constant";
import { Mutations } from "./mutations";


/**
 * 检查是否有权限
 * @param roles 角色列表 
 * @param route 当前路由 
 */
const hasPermission = (roles: string[], route: RouteRecordRaw) => {
  if (route.meta && route.meta.roles) {
    return roles.some(role => {
      if (route.meta?.roles !== undefined) {
        if (route.meta.roles instanceof String) {
          return route.meta.roles.includes(role)
        }
      }
    })
  } else {
    return true
  }
}

/**
 * 路由权限过滤器
 * @param routes 路由列表
 * @param roles 角色列表
 * @returns 有权限的路由列表
 */
const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
  const res: RouteRecordRaw[] = []
  routes.forEach(route => {
    const r = { ...route }
    if (hasPermission(roles, r)) {
      if (r.children) {
        r.children = filterAsyncRoutes(r.children, roles)
      }
      res.push(r)
    }
  })
  return res
}

type AugmentedActionContext = {
  commit<K extends keyof Mutations>(
    key: K,
    payload: Parameters<Mutations[K]>[1]
  ): ReturnType<Mutations[K]>
} & Omit<ActionContext<PermissionState, RootState>, 'commit'>

/**
 * 定义 Actions
 */
export interface Actions {
  [PermissionConstant.ACTION_SET_ROUTES]({ commit }: AugmentedActionContext, roles: string[]): void
}

export const actions:Actions & ActionTree<PermissionState, RootState> = {
  [PermissionConstant.ACTION_SET_ROUTES](
    { commit }: AugmentedActionContext,
    roles: string[]
  ) {
    let accessedRoutes
    if (roles.includes('admin')) {
      accessedRoutes = asyncRoutes
    } else {
      accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
    }
    commit(PermissionConstant.MUTATION_SET_ROUTES, accessedRoutes)
  }
}